/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
#include "gpio.h"
#include "rtc.h"
#include "bsp_led.h"
#include "bsp_usart.h"
#include "bsp_date.h"
#include "bsp_esp8266.h"
#include "bsp_esp8266_test.h"
#include "semphr.h"
#include "jsmn.h"
#include "oled.h"
#include "core_delay.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define USART_REC_LEN 200

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */

// usart init buffer
uint8_t aRxBuffer1;
uint8_t aRxBuffer3;		
uint8_t 	USART1_RX_BUF[USART_REC_LEN];		//usart1 receive buffer
uint16_t  USART1_RX_STA;									//usart1 receive buffer counter
uint8_t		Res;														//usart1 receive temp variable
uint8_t ucCh; 														//usart3 receive temp variable

char stringWeatherData[512];							//weather data in string format
int stringWeatherData_index = 0;					//weather data in string format counter
jsmn_parser jsonWeatherData;							//weather data in json format

/////// mutex oled used for i2c///////
StaticSemaphore_t i2cMutex;
SemaphoreHandle_t i2cMutexHandle;
/////// semaphore weather used ///////
StaticSemaphore_t weatherRevFinishedSemaphore;
SemaphoreHandle_t weatherRevFinishedSemaphoreHandle;

extern uint8_t ucTcpClosedFlag;					 //flag show whether tcp connected
extern struct STRUCT_USARTx_Fram strEsp8266_Fram_Record; //Esp8266 structure for receiving data

/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
const osThreadAttr_t defaultTask_attributes = {
  .name = "defaultTask",
  .stack_size = 128 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
void Task_Init(void *argument);
void Task_TimeDisplay(void *argument);
void Task_Weather(void *argument);

void parse_weather_data(const char *json);
/* USER CODE END FunctionPrototypes */

void StartDefaultTask(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
	i2cMutexHandle = xSemaphoreCreateMutexStatic( &i2cMutex );
	
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
	weatherRevFinishedSemaphoreHandle =  xSemaphoreCreateBinaryStatic( &weatherRevFinishedSemaphore );
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of defaultTask */
  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
	//xTaskCreate( InitTask, "InitTask", 128 * 4, NULL, configMAX_PRIORITIES, NULL );
	xTaskCreate( Task_Init, "Init", 128 * 4, NULL, configMAX_PRIORITIES, NULL );
	xTaskCreate( Task_TimeDisplay, "TimeDisplay", 128 * 4, NULL, configMAX_PRIORITIES-2, NULL );
	xTaskCreate( Task_Weather, "Weather", 128 * 20, NULL, configMAX_PRIORITIES-2 , NULL );
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  /* add events, ... */
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END StartDefaultTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
///////// tasks /////////
void Task_Init(void *argument){
	while(1){
		//Init USART1 interupt for debug
		HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer1, 1);
		printf("USART1 Interupt init finished!\n");
		//Init USART3 interupt for esp8266
		HAL_UART_Receive_IT(&huart3, (uint8_t *)&aRxBuffer3, 1);
		printf("USART3 Interupt init finished!\n");
		
		//Init esp8266 wifi module
		CPU_TS_TmrInit();      //Init DWT counter for delay                                               
		printf("ESP8266_Init finishing!\n");
		ESP8266_Init();
		printf("ESP8266_Init finished!\n");
		
		printf("ESP8266 configing!\n");
		ESP8266_StaTcpClient_Unvarnish_ConfigTest(); 
		printf("ESP8266 config finished!\n");
		
		vTaskDelete(NULL);
	}
}
void Task_TimeDisplay(void *argument){
	while(1){
		/* take  */
		/* display time */
		Time_Refresh();
	}
}
void Task_Weather(void *argument){
	while(1){
		vTaskDelay(5000);
		macESP8266_Usart("GET https://%s/v3/weather/now.json?key=%s&location=%s\r\n", macUser_ESP8266_TcpServer_IP, macUser_ESP8266_TcpServer_key, macUser_ESP8266_TcpServer_city);  
		//printf("GET https://%s/v3/weather/now.json?key=%s&location=%s\n", macUser_ESP8266_TcpServer_IP, macUser_ESP8266_TcpServer_key, macUser_ESP8266_TcpServer_city);  
		/* take signal */
		xSemaphoreTake(weatherRevFinishedSemaphoreHandle, portMAX_DELAY);
		/* read and parse data */
		ESP8266_RecvData();
		//printf("receiver data from esp8266:\n%s\n", stringWeatherData);
		char *weather_json_start = strchr(stringWeatherData, '{');  // 找到 JSON 数据的起始位置
    if (weather_json_start == NULL) {
        printf("No JSON data found.\n");
    }
		else{
			// 输出 JSON 数据部分
			printf("JSON data: %s\n", weather_json_start);
			
			parse_weather_data(weather_json_start);
			//printf("%s\n", strEsp8266_Fram_Record.Data_RX_BUF);
		}
	}
}

///////// parse json data /////////
void parse_weather_data(const char *json) {
    jsmntok_t tokens[128];  // 假设 JSON 有 32 个标记，适当调整

    jsmn_init(&jsonWeatherData);
    int ret = jsmn_parse(&jsonWeatherData, json, strlen(json), tokens, sizeof(tokens) / sizeof(tokens[0]));

    if (ret < 0) {
        printf("Failed to parse JSON: %d\n", ret);
        return;
    }

    // 遍历解析的 JSON tokens
    for (int i = 1; i < ret; i++) {
        if (strncmp("name", json + tokens[i].start, tokens[i].end - tokens[i].start) == 0) {
            // 获取城市名称
            char city[32];
            strncpy(city, json + tokens[i + 1].start, tokens[i + 1].end - tokens[i + 1].start);
            city[tokens[i + 1].end - tokens[i + 1].start] = '\0';
            printf("城市: %s\n", city);
        }

        if (strncmp("text", json + tokens[i].start, tokens[i].end - tokens[i].start) == 0) {
            // 获取天气文本
            char weather[32];
            strncpy(weather, json + tokens[i + 1].start, tokens[i + 1].end - tokens[i + 1].start);
            weather[tokens[i + 1].end - tokens[i + 1].start] = '\0';
            printf("天气: %s\n", weather);
        }

        if (strncmp("temperature", json + tokens[i].start, tokens[i].end - tokens[i].start) == 0) {
            // 获取温度
            char temperature[8];
            strncpy(temperature, json + tokens[i + 1].start, tokens[i + 1].end - tokens[i + 1].start);
            temperature[tokens[i + 1].end - tokens[i + 1].start] = '\0';
            printf("温度: %s度\n", temperature);
        }
    }
}
///////// ALL USART interupt call back function /////////
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart ->Instance == USART1)
    {
				if((USART1_RX_STA&0x8000)==0)
				{
					if(Res==0x0D)
					{
						USART1_RX_STA|=0x8000;
						HAL_UART_Receive_IT(&huart1, &Res, 1);
					}
					else
					{
						USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ;
						USART1_RX_STA++;
						if(USART1_RX_STA>(USART_REC_LEN-1))
							USART1_RX_STA=0;
					}		 
				}
				HAL_UART_Receive_IT(huart,&Res,1);
				printf("%c", Res);
    }
		else if(huart ->Instance == USART3){
			//printf("enter usart3 interupt\n");
			if(ucCh==0x0D) // finish
			{
				strEsp8266_Fram_Record .InfBit .FramFinishFlag = 1;
				ucTcpClosedFlag = strstr ( strEsp8266_Fram_Record .Data_RX_BUF, "CLOSED" ) ? 1 : 0;
				//printf("FramFinishFlag: %d ucTcpClosedFlag is %d\n", strEsp8266_Fram_Record .InfBit .FramFinishFlag, ucTcpClosedFlag);
				ucCh = 0;
				HAL_UART_Receive_IT(&huart3, &ucCh, 1);
				BaseType_t woken;
				xSemaphoreGiveFromISR( weatherRevFinishedSemaphoreHandle, &woken);
			}
			else
			{
				if ( strEsp8266_Fram_Record .InfBit .FramLength < ( RX_BUF_MAX_LEN - 1 ) )                       //预留1个字节写结束符
				 strEsp8266_Fram_Record .Data_RX_BUF [ strEsp8266_Fram_Record .InfBit .FramLength ++ ]  = ucCh;
				HAL_UART_Receive_IT(&huart3, &ucCh, 1);
			}	
		}
}

/* USER CODE END Application */

